/**
 * @preserve usage information:
 * 
 * This library provides some functionality that I've found useful for
 *  improving the quality of the javascript that I write:
 * 
 * A logger where the logging threshold may be set. It is a very simplistic
 *   version of log4j
 * 
 * Asserts that may be turned on or off, depending on the need (eg: a debug
 * 	 version and a production version).
 * 
 * A Types class that provides a few functions and adds a few methods to
 *   Object to allow javascript to support some basic (and optional) 
 *   type checking.
 * 
 * A few other utility functions that I've found useful from time to time.
 *
 *  Logger:
 *
 * Logger.debug(<message>)
 * Logger.info(<message>)
 * Logger.warn(<message>)
 * Logger.error(<message>)
 *
 *  it is activated by calling the Logger.level function:
 *
 * Logger.level(
 * 	   [Logger.NONE|Logger.DEBUG|Logger.INFO|Logger.WARN|Logger.ERROR])
 * eg:
 *
 * Logger.level(Logger.DEBUG);
 *
 * By default, log level is set to none. In this mode, none of the above
 *   log messages result in anything being printed to the console.
 *
 * Setting the log lovel to anything other than none results in all log
 *   messages at that level or higher printing to console.
 *
 * For example:
 *
 * Logger.level(Logger.INFO);
 * Logger.debug("this is a debug message");
 * Logger.info("this is a info message");
 * Logger.error("this is an error message");
 *
 * Would result in the following console output:
 *   this is a info message
 *   this is an error message
 *
 *
 * Assert:
 *
 * Assert.assertDefined(<var>, [message])
 * Assert.assertNotEquals(<var1>, <var2>, [message])
 * Assert.assertEquals(<var1>, <var2>, [message])
 * Assert.assert(<condition>, [message])
 *
 * Assert.assertsOff();
 * Assert.assertsOn();
 *
 * Import / Export:
 *    very much inspired by goog.exportSymbol(...)

    export allows you to define objects in any scope you want (eg: a closure) and 
      expose them, without unduly polluting the global scope. For example:
     
        (function() {
        	var object = { 
        		var that = {
        			property1:'foo';
        			property2:'bar';
        		}
        		return that;
        	};
        	Types.exportSymbol("js.mypackage.MyObject", object);
		})();
		
     Now you have an object called js.mypackage.MyObject defined and the only 
       thing you've added to the global scope is an object called js.
       if you've already defined something called js, this just adds mypackage to 
       it.
       
     If you find lots of new js.mypackage.MyObject() in your code to be too 
       verbose, you can use the import method:
       
       	Types.importSymbol("js.mypackage.MyObject");
     
     Now you can refer to this as new MyObject() (but you've added MyObject to)
        the global scope, so be careful.
        
     To avoid that, you can declare an object in the local scope to contain all
        your includes:
      
        var localScope = {};
        Types.importSymbol("js.mypackage.MyObject", localScope);
        
     Now you can refer to your object as localScope.MyObject.
    
 * 
 * Interfaces:
 *  
     As you might expect, interfaces allow you to define some expected methods
       or properties and then verify that other objects include them.
       
     First step is defining an interface, like so:
		
	(function() {
		//now js.mypackage.MyInterface is available on the global namespace
		Types.exportInterface("js.mypackage.MyInterface", {
			aMethod1:function(arg1, arg2) {},
			aMethod2:function(arg1, arg2) {}
		});
	})();

	 Now you can verify that your objects include those methods (with the correct)
	    number of arguments:
	 
	(function() {
		var MyObject1 = {
			aMethod1:function(arg1, arg2) {} //missing a method
		}
		var MyObject2 = {
			aMethod1:function(arg1) {}, //missing an argument
			aMethod2:function(arg1, arg2) {}
		}
		var MyObject3 = {
			aMethod1:function(arg1, arg2) {}, 
			aMethod2:function(arg1, arg2, arg3) {} //too many arguments
		}
		
		//these would all fail!
		Assert.assert(MyObject1.doesImplement(js.mypackage.MyInterface));
		Assert.assert(MyObject2.doesImplement(js.mypackage.MyInterface));
		Assert.assert(MyObject3.doesImplement(js.mypackage.MyInterface));
		
		var AnotherObject = {
			aMethod1:function(arg1, arg2) {},
			aMethod2:function(arg1, arg2) {},
			anotherMethod:function(arg1) {}
		}
		
		//but this doesn't fail, and allows you to verify that your 'class' is correctly implemented
		Assert.assert(AnotherObject.doesImplement(js.mypackage.MyInterface));
		Types.exportSymbol("js.mypackage.AnotherObject", AnotherObject);
	})();
 * 
 */

	/** @expose */
	initDevMode = function() {
		Logger.initDevMode();
		Assert.initDevMode();
	};

	/**
	 * TODO: move to utilities.js
	 * 
	 * Get a random string
	 * @param length
	 * @expose
	 */
	function randomString(length) {
		var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
		var randomstring = '';
		for (var i = 0; i < length; i++) {
			var rnum = Math.floor(Math.random() * chars.length);
			randomstring += chars.substring(rnum, rnum + 1);
		}
		return randomstring;
	}
